import re
import time
import threading
import datetime
from utils.e_mail import sendMail
from control.order_control import OrderType
from selenium import webdriver
from selenium.webdriver.common.by import By
from worker.base.base_worker import BaseWorker, Order
from utils.log_util import prints, saveLog
import constant.param_config as config
from constant.globl_constant import signalTag, indicator
from utils.time_util import current_time, local_stamp_2_gmt, stamp2datetime
from constant.globl_constant import mvSingal, indicatorSignal, strategyList


class TradeWorker(BaseWorker):
    """
    交易
    """
    lastDay = -1

    buyCache = 0
    sellCache = 0

    tradeStartTime = 3
    tradeEndTime = 10
    indicatorState = False
    alreadyLog = False

    def __init__(self):
        super().__init__()

    def startThread(self):
        """
        开启交易线程
        """
        thread = threading.Thread(target=self.getWebPage)
        # thread.daemon = True  # 设置线程为守护线程，以便在主程序退出时自动结束线程
        thread.start()

    def getWebPage(self):
        """
        判断市场状态、涨跌幅、是否存在禁止下单区间
        获取web页面数据
        解析数据
        """

        while True:
            if self.isLogin and self.marketClose() is False:
                # and self.passZone() is True:
                if self.extent(printLog=False) is False:
                    time.sleep(10)
                    continue

                if config.getSignalOrderStatus() is False:
                    time.sleep(10)
                    continue

                # 9点以后进行交易
                timeValue = datetime.datetime.now().hour
                if timeValue > self.tradeStartTime and timeValue < self.tradeEndTime:
                    time.sleep(10)
                    continue

                # 下单前检查，日内是否有重要事件发布
                if self.getForbidState(self.alreadyLog, "交易服务"):
                    # 日内有重要事件公布时，禁止交易
                    self.alreadyLog = True
                    time.sleep(10)
                    continue

                # 达到目标盈利后是否继续交易
                if self.tradeState() is False:
                    time.sleep(10)
                    continue

                if len(mvSingal) != 0 and len(indicatorSignal) != 0:
                    mvState = mvSingal[0]
                    indicatorState = indicatorSignal[0]
                    if current_time() - mvState[0] <= 60 and current_time(
                    ) - indicatorState[0] <= 60:
                        if mvState[1] is True and indicatorState[1] is True:
                            # # 价格在第一阻力之内，有挂单且未成交
                            # currentPrice = self.control.getCurrentPrice(
                            #     self.symble, orderType=Order.CREATE_BUY)
                            # if self.buyCache != 0 and currentPrice < self.sellCache - 3 and len(
                            #     [
                            #         item for item in self.getPositionsDetail()
                            #         if item.price_open == self.buyCache
                            #     ]) == 0:
                            saveLog("技术指标出现做多信号")
                            self.orderOperate(Order.CREATE_BUY)
                        elif mvState[1] is False and indicatorState[1] is False:
                            # # 价格在第一阻力之内，有挂单且未成交
                            # currentPrice = self.control.getCurrentPrice(
                            #     self.symble, orderType=Order.CREATE_SELL)
                            # if self.sellCache != 0 and currentPrice > self.buyCache + 3 and len(
                            #     [
                            #         item for item in self.getPositionsDetail()
                            #         if item.price_open == self.sellCache
                            #     ]) == 0:
                            saveLog("技术指标出现做空信号")
                            self.orderOperate(Order.CREATE_SELL)
                        else:
                            saveLog("暂无信号")
                    else:
                        saveLog("暂无信号")
                else:
                    saveLog("暂无信号")
            time.sleep(10)

        # while True:
        #     if self.isTrade() is True and self.extent() is True and self.passZone() is True:
        #         try:
        #             self.chrome = webdriver.Chrome(options=self.getConfig())
        #             self.chrome.get(self.url)

        #             contentValue = self.chrome.find_element(by=By.ID,
        #                                                             value="leftColumn")
        #             timeBar = contentValue.find_element(by=By.ID, value="technicalstudiesSubTabs")

        #             li_elements = timeBar.find_elements(By.TAG_NAME, "li")
        #             tradeState = self.clickElements(li_elements, contentValue)
        #             self.createOrder(tradeState)
        #         except Exception as e:
        #             prints("网页解析异常，" + str(config.getChromeSleep()) + "s后重试，详情：" + str(e))
        #         self.chrome.close()
        #     time.sleep(config.getChromeSleep())

    def getConfig(self):
        """
        webdriver配置
        """
        chrome_options = webdriver.ChromeOptions()
        chrome_options.headless = True
        chrome_options.add_experimental_option("excludeSwitches",
                                               ["enable-logging"])
        chrome_options.add_argument('ignore-certificate-errors')
        return chrome_options

    def clickElements(self, list_elements, contentValue):
        """
        模拟点击，获取动态数据
        """
        try:
            timeMap = {}
            for li in list_elements:
                if li.text not in ["每小时", "5 小时", "每日", "每周", "每月"]:
                    self.chrome.execute_script("arguments[0].click();", li)
                    time.sleep(3)
                    value = str(
                        contentValue.find_element(
                            by=By.ID, value="techStudiesInnerWrap").text)
                    timeMap[li.text] = self.spliteStr(value)
            mapValue = timeMap.values()
            is_buy = all(value == 1 for value in mapValue)
            is_sell = all(value == 2 for value in mapValue)
            if is_buy:
                return 1
            elif is_sell:
                return 2
            else:
                saveLog("暂无信号")
                return None
        except:
            saveLog("模拟点击异常，网页关闭")
            return None

    def indicatorSignalOrder(self, t):
        """
        指标信号订单
        """

        if config.getIndicatorTrade():
            nowTime = datetime.datetime.now()
            hourNow = nowTime.hour
            if hourNow > 22 or hourNow < 3:
                historyOrder = self.dayAllOrder()
                positionList = self.getPositionsDetail(symbol=self.symble)

                if self.indicatorState is False and len(
                        historyOrder) == 0 and len(positionList) == 0:

                    self.indicatorState = True
                    if t == Order.CREATE_SELL:
                        currentPrice = self.control.getCurrentPrice(
                            self.symble, Order.CREATE_SELL)
                        if self.surpassPrice(t, currentPrice) is False:
                            self.control.createOrder(OrderType.SELL,
                                                     self.symble,
                                                     priceTp=currentPrice - 2,
                                                     remark=indicator)
                        else:
                            saveLog("当前价格未超过上一单平仓价，禁止指标信号下空单")
                    elif t == Order.CREATE_BUY:
                        currentPrice = self.control.getCurrentPrice(
                            self.symble, Order.CREATE_BUY)
                        if self.surpassPrice(t, currentPrice) is False:
                            self.control.createOrder(OrderType.BUY,
                                                     self.symble,
                                                     priceTp=currentPrice + 2,
                                                     remark=indicator)
                        else:
                            saveLog("当前价格未超过上一单平仓价，禁止指标信号下多单")
                return False
        self.indicatorState = False
        return True

    def spliteStr(self, s):
        """
        使用正则解析，获取核心数据
        """
        try:
            result_ma = re.search(r'移动平均指数:(.*?)技术指标', s, re.S).group(1)
            result_ti = re.search(r'技术指标:(.*?)$', s, re.S).group(1)

            ma_buy = int(
                re.search(r'买入 \((.*?)\)卖出', result_ma, re.S).group(1))
            ma_sell = int(re.search(r'卖出 \((.*?)\)', result_ma, re.S).group(1))

            ti_buy = int(
                re.search(r'买入 \((.*?)\)卖出', result_ti, re.S).group(1))
            ti_sell = int(re.search(r'卖出 \((.*?)\)', result_ti, re.S).group(1))

            if (ma_buy >= 8 or ma_sell <= 2) == True and (ti_buy >= 8
                                                          or ti_sell <= 2):
                return 1
            elif (ma_sell >= 8 or ma_buy <= 2) == False and (ti_sell >= 8
                                                             or ti_buy <= 2):
                return 2
            else:
                return None
        except:
            return None

    def orderOperate(self, state):
        """
        订单操作
        """

        # 存在非信号单
        if self.sameRemarkOrder(signalTag, reversal=True):
            saveLog("存在其他类型订单，信号单禁止下单")
            return

        # 限定时间内没有交易，进行指标信号下单
        if self.indicatorSignalOrder(state) is False:
            return

        orderTag = signalTag
        if self.getPlanState(None, None) is False:
            orderTag = signalTag + "_附加单"

        if self.forbid(state) is False:
            tp = self.getStrategyTp(state)
            if state == Order.CREATE_BUY:
                self.control.createOrder(OrderType.BUY,
                                         self.symble,
                                         priceTp=tp,
                                         priceSp=None,
                                         remark=orderTag)
            elif state == Order.CREATE_SELL:
                self.control.createOrder(OrderType.SELL,
                                         self.symble,
                                         priceTp=tp,
                                         priceSp=None,
                                         remark=orderTag)
            else:
                saveLog("下单异常")

    # def articlePointCheck(self, state):
    #     """
    #     文章关键点位判断
    #     state   1:下多单    2:下空单
    #     """
    #     currentPrice = self.control.getCurrentPrice(symbol=self.symble)
    #     buyPrice, sellPrice, coreStrategy = self.articlePrice()
    #     if buyPrice != 0 and sellPrice != 0 and sellPrice - buyPrice > 10 and currentPrice > buyPrice + 3 and currentPrice < sellPrice - 3:
    #         return True
    #     return False

    def articleTrade(self):
        """
        文章策略交易
        buyCache、sellCache作为下单限定, 当日内只能下一个多单和一个空单
        """

        timeNow = datetime.datetime.now().day
        if self.lastDay != timeNow:
            self.lastDay = timeNow
            self.buyCache = 0
            self.sellCache = 0
            allOrder = self.getLimitOrderDetail(symbol=self.symble)
            # 删除前一天挂单
            for item in allOrder:
                orderDay = stamp2datetime(local_stamp_2_gmt(
                    item.time_setup)).day
                if timeNow != orderDay:
                    self.closeOrder(item)

        buyPrice, sellPrice, coreStrategy = self.articlePrice()
        if buyPrice != 0 and sellPrice != 0:
            if self.buyCache != 0 and buyPrice != self.buyCache:
                # 是否存在该挂单，存在的话就修改，不存在的话则为已成交
                if self.changeLimitOrder(self.buyCache, buyPrice,
                                         self.ORDER_TYPE_BUY_LIMIT):
                    self.buyCache = buyPrice
            elif self.buyCache == 0:
                if self.sendLimitOrder(buyPrice, sellPrice,
                                       self.ORDER_TYPE_BUY_LIMIT):
                    self.buyCache = buyPrice

            if self.sellCache != 0 and sellPrice != self.sellCache:
                # 是否存在该挂单，存在的话就修改，不存在的话则为已成交
                if self.changeLimitOrder(self.sellCache, sellPrice,
                                         self.ORDER_TYPE_SELL_LIMIT):
                    self.sellCache = sellPrice
            elif self.sellCache == 0:
                if self.sendLimitOrder(sellPrice, buyPrice,
                                       self.ORDER_TYPE_SELL_LIMIT):
                    self.sellCache = sellPrice

    def sendLimitOrder(self, price, tp, t):
        """
        下挂单
        """
        limitSp = 0

        if t == self.ORDER_TYPE_BUY_LIMIT:
            limitSp = price - 5
        elif t == self.ORDER_TYPE_SELL_LIMIT:
            limitSp = price + 5

        result = self.control.createOrder(t,
                                          self.symble,
                                          limitPrice=price,
                                          limitSp=limitSp,
                                          limitTp=tp)
        if result is not None and result.retcode == self.TRADE_RETCODE_DONE:
            return True
        return False

    def changeLimitOrder(self, lastPrice, currentPrice, orderType):
        """
        修改挂单价格
        是否存在该挂单，存在的话就修改
        """
        state = False
        for order in self.getLimitOrderDetail(symbol=self.symble,
                                              price=lastPrice,
                                              t=orderType):
            sp = 0
            if orderType == self.ORDER_TYPE_BUY_LIMIT:
                sp = currentPrice - 5
            elif orderType == self.ORDER_TYPE_SELL_LIMIT:
                sp = currentPrice + 5

            result = self.control.changeOrder(order,
                                              sp,
                                              0,
                                              price=currentPrice,
                                              t=2)
            state = True

        if state:
            saveLog("修改挂单完成")
        return state
